#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>
#include <list>
#include <cstring>
#include <functional>
#include <fstream>
#include <iterator>

using namespace std;

void pr_10_1(vector<int> &ivec, int val)
{
    cout << count(ivec.cbegin(), ivec.cend(), val) << endl;
}

void pr_10_2(list<string> &slist, string s)
{
    cout << count(slist.cbegin(), slist.cend(), s) << endl;
}

int pr_10_3(vector<int> ivec)
{
   return accumulate(ivec.cbegin(), ivec.cend(), 0);
}

double pr_10_4(vector<double> dvec)
{
    return accumulate(dvec.cbegin(), dvec.cend(), 0);
}

void pr_10_5()
{
    const char *p[] = {"Hello", "World", "!"};
    const char *q[] = {strdup(p[0]), strdup(p[1]), strdup(p[2])};
    const char *r[] = {p[0], p[1], p[2]};
    cout << equal(begin(p), end(p), q) << endl;
    cout << equal(begin(p), end(p), r) << endl;
}

void pr_10_6()
{
    vector<int> ivec = {0,1,2,3,4,5,6,7,8,9};
    fill_n(ivec.begin(), ivec.size(), 0);
    for (auto &i : ivec) {
        cout << i << " ";
    }
    cout << endl;
}

void pr_10_7()
{
    vector<int> vec;
    list<int> lst;
    int i;
    while (cin >> i) {
        lst.push_back(i);
    }
//    copy(lst.cbegin(), lst.cend(), vec.begin()); // 错误
    copy(lst.cbegin(), lst.cend(), back_inserter(vec));

    vector<int> ivec;
    ivec.reserve(10);
//    fill_n(ivec.begin(), 10, 0);  // 错误
    fill_n(back_inserter(ivec), 10, 0);
}

void pr_10_9(vector<string> words)
{
    cout << "input words: " << endl;
    for (auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
    sort(words.begin(), words.end());
    cout << "after sort: " << endl;
    for (auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
    auto end_unique = unique(words.begin(), words.end());
    cout << "after unique: " << endl;
    for (auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
    words.erase(end_unique, words.end());
    cout << "after erase: " << endl;
    for (auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
}

void elimDups(vector<string> &words)
{
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());
    words.erase(end_unique, words.end());
}

bool isShorter(const string &s1, const string &s2)
{
    return s1.size() < s2.size();
}

void pr_10_11()
{
    vector<string> words{"the", "quick", "red", "fox", "jumps", "over",
                        "the", "slow", "red", "turtle"};
    elimDups(words);
    sort(words.begin(), words.end(), isShorter);
    for (const auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
    stable_sort(words.begin(), words.end(), isShorter);
    for (const auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
}

bool compareStringSize(const string &s)
{
    return s.size() >= 5 ? true : false;
}

void pr_10_13()
{
    vector<string> words{"the", "quick", "red", "fox", "jumps", "over",
                        "the", "slow", "red", "turtle"};
    auto end_part = partition(words.begin(), words.end(), compareStringSize);
    for (auto it = words.begin(); it != end_part; it++) {
        cout << *it << " ";
    }
    cout << endl;
}

void pr_10_14()
{
    auto a = [](int a, int b) { return a + b; };
    cout << a(3, 4) << endl;
}

void pr_10_15(int i)
{
    auto b = [i](int j) { return i + j; };
}

void pr_10_16(vector<string> &words, vector<string>::size_type sz)
{
    elimDups(words);
    stable_sort(words.begin(), words.end(),
                [](const string &a, const string &b)
                    { return a.size() < b.size();} );
    auto wc = find_if(words.begin(), words.end(),
                      [sz](const string &a)
                        { return a.size() >= sz; } );
    auto count = words.end() - wc;
    for_each(wc, words.end(),
             [](const string &s) { cout << s << " ";});
    cout << endl;
}

void pr_10_18(vector<string> &words, vector<string>::size_type sz)
{
    elimDups(words);
    for_each(words.begin(), words.end(),
             [](const string &s){ cout << s << "";});
    cout << endl;
    auto wc = partition(words.begin(), words.end(),
                        [sz](const string &s){ return s.size() >= sz;});
    auto count = wc - words.begin();
    for_each(words.begin(), wc,
             [](const string &s){ cout << s << "";});
    cout << endl;
}

void pr_10_19(vector<string> &words, vector<string>::size_type sz)
{
    elimDups(words);
    for_each(words.begin(), words.end(),
             [](const string &s){ cout << s << "";});
    cout << endl;
    auto wc = stable_partition(words.begin(), words.end(),
                        [sz](const string &s){ return s.size() >= sz;});
    auto count = wc - words.begin();
    for_each(words.begin(), wc,
             [](const string &s){ cout << s << "";});
    cout << endl;
}

void pr_10_20(vector<string> words, vector<string>::size_type sz)
{
    elimDups(words);
    // 打印排序后的字符串
    for_each(words.begin(), words.end(),
             [](const string s) { cout << s << " "; });
    cout << endl;
    auto count = count_if(words.begin(), words.end(),
                          [sz](const string &s) { return s.size() >= sz; });
    cout << count << endl;
}

void pr_10_21(void)
{
    int i = 5;
    auto f = [i]() mutable->bool {
        if (i > 0) { i--; return false; }
        else return true;
    };
    for (int j = 0; j < 6; j++) {
        cout << f() << " ";
    }
    cout << endl;
}

void output_words(vector<string> &words)
{
    for (auto iter = words.begin(); iter != words.end(); iter++) {
        cout << *iter << " ";
    }
    cout << endl;
}

bool check_size(const string &s, string::size_type sz)
{
    return s.size() >= sz;
}

void pr_10_22(vector<string> &words, vector<string>::size_type sz)
{
    output_words(words);
    // 统计满足 size() >= sz 的元素的个数
    auto bc = count_if(words.begin(), words.end(),
                       bind(check_size, std::placeholders::_1, sz));
    cout << bc << " " << endl;
}

void pr_10_27()
{
    vector<int> vi = {1,2,2,3,4,5,5,6};
    list<int> lst;
    unique_copy(vi.cbegin(), vi.cend(), back_inserter(lst));
    for (auto &v : lst) {
        cout << v << " ";
    }
    cout << endl;
}

void pr_10_28()
{
    vector<int> vi = {1,2,3,4,5,6,7,8,9};
    list<int> lst1, lst2, lst3;
    unique_copy(vi.begin(), vi.end(), back_inserter(lst1));
    unique_copy(vi.cbegin(), vi.cend(), front_inserter(lst2));
    unique_copy(vi.cbegin(), vi.cend(), inserter(lst3, lst3.begin()));
}

int pr_10_29(int argc, char* argv[])
{
    ifstream in(argv[1]);
    if (!in) {
        cout << "打开输入文件失败" << endl;
        exit(1);
    }
    // 创建流迭代器从文件读入字符串
    istream_iterator<string> in_iter(in);
    // 创建尾后迭代器
    istream_iterator<string> eof;
    // 创建容纳string的vector
    vector<string> words;
    while (in_iter != eof) {
        words.push_back(*in_iter++);  // 存入 vector并递增迭代器
    }
    for (auto &v : words) {
        cout << v << " ";
    }
    cout << endl;
    return 0;
}

void pr_10_30()
{
    istream_iterator<int> in_iter(cin), eof;
    vector<int> vi;
    while (in_iter != eof) {
        vi.push_back(*in_iter++);
    }
    sort(vi.begin(), vi.end());

    ostream_iterator<int> out_iter(cout, " ");
    copy(vi.begin(), vi.begin(), out_iter);
}

void pr_10_31()
{
    istream_iterator<int> in_iter(cin), eof;
    vector<int> vi;
    while (in_iter != eof) {
        vi.push_back(*in_iter++);
    }
    sort(vi.begin(), vi.end());

    ostream_iterator<int> out_iter(cout, " ");
    unique_copy(vi.begin(), vi.end(), out_iter);
}

int pr_10_33(int argc, char *argv[])
{
    if (argc != 4) {
        cout << "用法: execise.exe in_file out_file1 out_file2" << endl;
        return -1;
    }

    ifstream in(argv[1]);
    if (!in) {
        cout << "打开输入文件错误" << endl;
        exit(1);
    }

    ofstream out1(argv[2]);
    if (!out1) {
        cout << "打开输出文件 1 失败" << endl;
        exit(1);
    }

    ofstream out2(argv[3]);
    if (!out2) {
        cout << "打开输出文件 2 失败" << endl;
        exit(1);
    }

    // 创建流迭代器从文件读入整数
    istream_iterator<int> in_iter(in);
    // 尾后迭代器
    istream_iterator<int> eof;
    // 第一个输出文件以空格间隔整数
    ostream_iterator<int> out_iter1(out1, " ");
    // 第二个输出文件以换行间隔整数
    ostream_iterator<int> out_iter2(out2, "\n");
    while (in_iter != eof) {
        if (*in_iter & 1) {  // 奇数写入第一个输出文件
            *out_iter1++ = *in_iter;
        } else {  // 偶数写入第二个输出文件
            *out_iter2++ = *in_iter;
        }
        in_iter++;
    }
    return 0;
}

void pr_10_34()
{
    vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
    for (auto it = vi.rbegin(); it != vi.rend(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
}

void pr_10_35()
{
    vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
    for (auto it = vi.end(); it != vi.begin(); ) {
        cout << *(--it) << " ";
    }
    cout << endl;
}

void pr_10_36()
{
    list<int> li = {0,1,2,0,3,4,6,0,8,0,10};
    // 利用反向迭代器查找最后一个 0
    auto last_z = find(li.rbegin(), li.rend(), 0);
    // 将迭代器向链表头方向推进一个位置
    // 转换为普通迭代器时，将回到最后一个 0的位置
    last_z++;
    int p = 1;
    // 用 base 将 last_t 转换为普通迭代器
    // 从链表头开始遍历，计数最后一个 0 的编号
    for (auto iter = li.begin(); iter != last_z.base(); iter++, p++) {
    }
    if (p >= li.size()) { // 未找到 0
        cout << "容器中没有 0" << endl;
    } else {
        cout << "最后一个 0 在位置 " << p << endl;
    }
}

void pr_10_37()
{
    ostream_iterator<int> out_iter(cout, " ");
    vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
    // 用流迭代器和 copy输出 vi
    copy(vi.begin(), vi.end(), out_iter);
    cout << endl;

    list<int> li;
    // 将 vi[2], 也就是第3个元素的位置转换为反向迭代器
    vector<int>::reverse_iterator re(vi.begin() + 2);
    // 将 vi[7], 也就是第8个元素的位置转换为反向迭代器
    vector<int>::reverse_iterator rb(vi.begin() + 7);
    // 用反向迭代器将元素逆序拷贝到 list
    copy(rb, re, back_inserter(li));
    copy(li.begin(), li.end(), out_iter);
    cout << endl;
}

void pr_10_42()
{
    list<string> words;
    string word;
    while (cin >> word) {
        words.push_back(word);
    }
    words.sort();
    words.unique();
}

int main()
{
    vector<string> words{"the", "quick", "red", "fox", "jumps", "over",
                        "the", "slow", "red", "turtle"};
    pr_10_36();
    return 0;
}
